DepositData.tsx 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328
  1. "use client";
  2. import { DepositsTypes, RewardsType } from "@/api/depositsApi";
  3. import { getUserMoneyApi, getUserRechargeApi } from "@/api/user";
  4. import Box from "@/components/Box";
  5. import ButtonOwn from "@/components/ButtonOwn";
  6. import TipsModal, { ModalProps } from "@/components/TipsModal";
  7. import { useUserInfoStore } from "@/stores/useUserInfoStore";
  8. import { neReg } from "@/utils";
  9. import { Button, Form, Input, Toast } from "antd-mobile";
  10. import { FormInstance } from "antd-mobile/es/components/form";
  11. import { useTranslations } from "next-intl";
  12. import { FC, Fragment, useLayoutEffect, useRef, useState } from "react";
  13. import actions from "@/app/[locale]/(TabBar)/deposit/actions";
  14. import Empty from "@/components/Empty";
  15. import "@/styles/deposit.scss";
  16. import { server } from "@/utils/client";
  17. import Image from "next/image";
  18. interface Props {}
  19. interface RewardsProps {
  20. rewards: RewardsType[];
  21. }
  22. const RewardsText: FC<RewardsProps> = (props) => {
  23. const { rewards } = props;
  24. // {/*1现金2彩金3免费币4重玩币*/}
  25. const t = useTranslations();
  26. const calcRewards = rewards
  27. .map((item) => {
  28. // let text = item.ratio > 0 ? `${item.ratio}%` : `${item.reward}`;
  29. // 根据coin_type添加后缀
  30. const suffixes = {
  31. 1: t("ProfilePage.balance"),
  32. 2: t("ProfilePage.bonus"),
  33. 3: t("ProfilePage.free"),
  34. 4: t("ProfilePage.replay"),
  35. };
  36. let text = "";
  37. // 设置基础奖励文本
  38. if (item.ratio > 0) {
  39. text = `${item.ratio}%`;
  40. } else {
  41. text = `${item.reward}`;
  42. }
  43. if (item.ratio > 0 && item.reward > 0) {
  44. text = `${item.ratio}%${suffixes[item.coin_type]}, ${item.reward}`;
  45. }
  46. // 如果coin_type在suffixes中存在,则添加相应的后缀
  47. if (suffixes.hasOwnProperty(item.coin_type)) {
  48. text += suffixes[item.coin_type];
  49. }
  50. return text;
  51. })
  52. .join(",");
  53. return (
  54. <div className={"flex flex-1 flex-wrap break-all"}>
  55. <span className="amountTips">+ {calcRewards} </span>
  56. </div>
  57. );
  58. };
  59. const getDepositApi = async () => {
  60. return server
  61. .request<DepositsTypes[]>({
  62. url: "/v1/api/user/user_deposit_config",
  63. method: "post",
  64. data: { activity_type: 0 },
  65. })
  66. .then((res) => {
  67. if (res.code === 200) return res.data;
  68. return [];
  69. });
  70. };
  71. const DepositData: FC<Props> = (props) => {
  72. const t = useTranslations();
  73. const userInfo = useUserInfoStore((state) => state.userInfo);
  74. const [depositState, setDepositState] = useState<DepositsTypes[]>([]);
  75. const [activeType, setActiveType] = useState<Partial<DepositsTypes>>({});
  76. const formInstanceRef = useRef<FormInstance>(null);
  77. let [amount, setAmount] = useState<number | undefined>(undefined);
  78. const titleChangeHandler = (item: DepositsTypes, index: number) => {
  79. setAmount(undefined);
  80. setActiveType(item);
  81. formInstanceRef.current?.resetFields();
  82. };
  83. const isStrictMode = true;
  84. const tipModelRef = useRef<ModalProps>(null); // 充值清空打码量弹窗
  85. const [formData, setFormData] = useState<any>({}); // 存放表单数据
  86. const onFinish = async (values: any) => {
  87. const params = { ...values, channel_id: activeType.id, amount: +values.amount };
  88. const res = await getUserMoneyApi();
  89. console.log(`🚀🚀🚀🚀🚀-> in DepositData.tsx on 99`, res);
  90. if (res.data?.tips_reset_rollover) {
  91. tipModelRef.current?.onOpen();
  92. setFormData(params);
  93. return;
  94. }
  95. handleUserRecharge(false, params);
  96. };
  97. const handleUserRecharge = (is_reset_rollover: boolean, data?: any) => {
  98. let params = data || formData;
  99. getUserRechargeApi({ is_reset_rollover, ...params })
  100. .then(async (res) => {
  101. formInstanceRef.current?.resetFields();
  102. Toast.show({ icon: "success", content: t("code.200"), maskClickable: false });
  103. tipModelRef.current?.onClose();
  104. setAmount(undefined);
  105. if (res.data.pay_url) {
  106. window.open(res.data.pay_url);
  107. }
  108. const data = await getDepositApi();
  109. setDepositState(data);
  110. setActiveType(data[0]);
  111. await actions();
  112. })
  113. .catch((error) => {
  114. Toast.show({ content: t(`code${error.data.code}`), maskClickable: false });
  115. });
  116. };
  117. const onValuesChange = (changeValues: any) => {
  118. if (changeValues.amount) {
  119. setAmount(changeValues.amount);
  120. }
  121. };
  122. const amountChange = (value: number) => {
  123. formInstanceRef.current?.setFieldValue("amount", value);
  124. setAmount(value);
  125. };
  126. const amountValidator = (rules: any, value: any) => {
  127. if (!value) return Promise.reject(new Error(t("form.amount")));
  128. if (+value < activeType.min_amount!)
  129. return Promise.reject(
  130. new Error(t("form.amountMinReg", { amount: activeType.min_amount }))
  131. );
  132. if (+value > activeType.max_amount!)
  133. return Promise.reject(
  134. new Error(t("form.amountMaxReg", { amount: activeType.max_amount }))
  135. );
  136. return Promise.resolve();
  137. };
  138. useLayoutEffect(() => {
  139. getDepositApi().then((data) => {
  140. setDepositState(data);
  141. setActiveType(data[0]);
  142. });
  143. }, []);
  144. if (!depositState.length) return <Empty />;
  145. return (
  146. <div className="deposit-box">
  147. <div className="img-box">
  148. <Image
  149. className={"h-[100%] w-[100%] object-cover"}
  150. src={activeType.icon || ""}
  151. alt={activeType.name || ""}
  152. width={160}
  153. height={40}
  154. />
  155. </div>
  156. <div className={"flex flex-wrap"}>
  157. {depositState.map((item, index) => {
  158. return (
  159. <Fragment key={item.id}>
  160. <p
  161. className="btn-box truncate"
  162. style={{
  163. borderColor: activeType?.id === item.id ? "#ff9323" : "#333",
  164. }}
  165. onClick={() => titleChangeHandler(item, index)}
  166. >
  167. {item.name}
  168. </p>
  169. </Fragment>
  170. );
  171. })}
  172. </div>
  173. <Box className={"custom-form"} style={{ padding: 0 }}>
  174. <Form
  175. style={{
  176. "--border-bottom": "none",
  177. "--border-top": "none",
  178. "--border-inner": "none",
  179. }}
  180. ref={formInstanceRef}
  181. footer={
  182. <>
  183. <ButtonOwn active>{t("DepositPage.DepositarAgora")}</ButtonOwn>
  184. </>
  185. }
  186. initialValues={userInfo}
  187. onFinish={onFinish}
  188. onValuesChange={onValuesChange}
  189. >
  190. {isStrictMode ? (
  191. <>
  192. <Form.Item
  193. name="user_name"
  194. label=""
  195. rules={[{ required: true, message: t("form.usernameReg") }]}
  196. >
  197. <Input placeholder={t("form.username")} />
  198. </Form.Item>
  199. <Form.Item
  200. name="passport"
  201. label=""
  202. rules={[
  203. { required: true, message: t("form.cardReg"), pattern: neReg },
  204. ]}
  205. >
  206. <Input placeholder={t("form.card")} maxLength={11} type={"text"} />
  207. </Form.Item>
  208. </>
  209. ) : null}
  210. <Form.Item
  211. name="amount"
  212. label=""
  213. rules={[{ required: true, type: "number", validator: amountValidator }]}
  214. >
  215. <Input
  216. placeholder={`${t("DepositPage.Montante")}(BRL): Mín. ${activeType?.min_amount}`}
  217. type={"number"}
  218. maxLength={activeType?.max_amount}
  219. />
  220. </Form.Item>
  221. <div className={"flex flex-col"}>
  222. <div className={"flex-1"}>
  223. <ul className="ul-box">
  224. {activeType?.products?.map((item, index) => (
  225. <li
  226. className={amount == item.amount ? "active" : ""}
  227. key={index}
  228. onClick={() => amountChange(item.amount)}
  229. >
  230. {!!item.badge && <span className="hot"></span>}
  231. <div className="amountContent">
  232. {/* <span className="iconfont icon-unit-brl"></span> */}
  233. <span className="iconfont">R$</span>
  234. <span> {item.amount}</span>
  235. </div>
  236. {item.rewards && (
  237. <RewardsText
  238. rewards={
  239. item.rewards &&
  240. item.rewards.sort(
  241. (p, n) => p.coin_type - n.coin_type
  242. )
  243. }
  244. />
  245. )}
  246. </li>
  247. ))}
  248. </ul>
  249. </div>
  250. </div>
  251. </Form>
  252. <div className={"mt-[5px] text-[0.12rem] text-primary-color"}>
  253. {t("DepositPage.depositTips")}
  254. </div>
  255. </Box>
  256. <TipsModal title={"Tips"} ref={tipModelRef}>
  257. <div className={"flex items-center justify-between"}>
  258. <h2 className={"text-[0.14rem]"}>Mantenha Bônus</h2>
  259. <Button
  260. color={"primary"}
  261. className={"mx-auto"}
  262. style={{
  263. "--background-color": "var(--primary-color)",
  264. "--border-color": "var(--primary-color)",
  265. }}
  266. onClick={() => handleUserRecharge(false)}
  267. >
  268. Depósito
  269. </Button>
  270. </div>
  271. <p className={"mt-[0.05rem] text-left text-[0.12rem] font-medium text-[#666]"}>
  272. Recarga direta, mantendo a carteira principal e informações de carteira de
  273. bônus;
  274. </p>
  275. <b
  276. className={"mb-[0.2rem] mt-[0.2rem]"}
  277. style={{
  278. width: "100%",
  279. height: "auto",
  280. borderTop: "1px solid #e5e5e5",
  281. display: "block",
  282. }}
  283. ></b>
  284. <div className={"flex items-center justify-between"}>
  285. <h2 className={"text-[0.14rem]"}>Esvaziem Bônus</h2>
  286. <Button
  287. color={"primary"}
  288. className={"mx-auto"}
  289. style={{
  290. "--background-color": "var(--primary-color)",
  291. "--border-color": "var(--primary-color)",
  292. }}
  293. onClick={() => handleUserRecharge(true)}
  294. >
  295. Depósito
  296. </Button>
  297. </div>
  298. <p className={"mt-[0.05rem] text-left text-[0.12rem] font-medium text-[#666]"}>
  299. Após a recarga, o saldo principal é mantido e todo o bônus é esvaziado, a nova
  300. carteira principal e a carteira de bônus são re-gravadas a quantidade de códigos
  301. jogados;
  302. </p>
  303. </TipsModal>
  304. </div>
  305. );
  306. };
  307. export default DepositData;